# uncompyle6 version 3.2.3
# Python bytecode 3.6 (3379)
# Decompiled from: Python 3.6.8 |Anaconda custom (64-bit)| (default, Feb 21 2019, 18:30:04) [MSC v.1916 64 bit (AMD64)]
# Embedded file name: site-packages\cryptography\x509\name.py
from __future__ import absolute_import, division, print_function
from enum import Enum
import six
from cryptography import utils
from cryptography.x509.oid import NameOID, ObjectIdentifier


class _ASN1Type(Enum):
    UTF8String = 12
    NumericString = 18
    PrintableString = 19
    T61String = 20
    IA5String = 22
    UTCTime = 23
    GeneralizedTime = 24
    VisibleString = 26
    UniversalString = 28
    BMPString = 30


_ASN1_TYPE_TO_ENUM = dict(((i.value, i) for i in _ASN1Type))
_SENTINEL = object()


class NameAttribute(object):
    def __init__(self, oid, value, _type=_SENTINEL):
        if not isinstance(oid, ObjectIdentifier):
            raise TypeError("oid argument must be an ObjectIdentifier instance.")
        if not isinstance(value, six.text_type):
            raise TypeError("value argument must be a text type.")
        if oid == NameOID.COUNTRY_NAME or oid == NameOID.JURISDICTION_COUNTRY_NAME:
            if len(value.encode("utf8")) != 2:
                raise ValueError("Country name must be a 2 character country code")
            if _type == _SENTINEL:
                _type = _ASN1Type.PrintableString
        if len(value) == 0:
            raise ValueError("Value cannot be an empty string")
        if _type == _SENTINEL:
            _type = _ASN1Type.UTF8String
        if not isinstance(_type, _ASN1Type):
            raise TypeError("_type must be from the _ASN1Type enum")
        self._oid = oid
        self._value = value
        self._type = _type

    oid = utils.read_only_property("_oid")
    value = utils.read_only_property("_value")

    def __eq__(self, other):
        if not isinstance(other, NameAttribute):
            return NotImplemented
        else:
            return self.oid == other.oid and self.value == other.value

    def __ne__(self, other):
        return not self == other

    def __hash__(self):
        return hash((self.oid, self.value))

    def __repr__(self):
        return ("<NameAttribute(oid={0.oid}, value={0.value!r})>").format(self)


class RelativeDistinguishedName(object):
    def __init__(self, attributes):
        attributes = frozenset(attributes)
        if not attributes:
            raise ValueError("a relative distinguished name cannot be empty")
        if not all((isinstance(x, NameAttribute) for x in attributes)):
            raise TypeError("attributes must be an iterable of NameAttribute")
        self._attributes = attributes

    def get_attributes_for_oid(self, oid):
        return [i for i in self if i.oid == oid]

    def __eq__(self, other):
        if not isinstance(other, RelativeDistinguishedName):
            return NotImplemented
        else:
            return self._attributes == other._attributes

    def __ne__(self, other):
        return not self == other

    def __hash__(self):
        return hash(self._attributes)

    def __iter__(self):
        return iter(self._attributes)

    def __len__(self):
        return len(self._attributes)

    def __repr__(self):
        return ("<RelativeDistinguishedName({0!r})>").format(list(self))


class Name(object):
    def __init__(self, attributes):
        attributes = list(attributes)
        if all((isinstance(x, NameAttribute) for x in attributes)):
            self._attributes = [RelativeDistinguishedName([x]) for x in attributes]
        else:
            if all((isinstance(x, RelativeDistinguishedName) for x in attributes)):
                self._attributes = attributes
            else:
                raise TypeError(
                    "attributes must be a list of NameAttribute or a list RelativeDistinguishedName"
                )

    def get_attributes_for_oid(self, oid):
        return [i for i in self if i.oid == oid]

    @property
    def rdns(self):
        return self._attributes

    def public_bytes(self, backend):
        return backend.x509_name_bytes(self)

    def __eq__(self, other):
        if not isinstance(other, Name):
            return NotImplemented
        else:
            return self._attributes == other._attributes

    def __ne__(self, other):
        return not self == other

    def __hash__(self):
        return hash(tuple(self._attributes))

    def __iter__(self):
        for rdn in self._attributes:
            for ava in rdn:
                yield ava

    def __len__(self):
        return sum((len(rdn) for rdn in self._attributes))

    def __repr__(self):
        return ("<Name({0!r})>").format(list(self))
